package com.xwltz.core.utils;

import cn.hutool.core.bean.copier.BeanCopier;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import org.springframework.context.ApplicationContext;

import javax.annotation.Nonnull;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @description BeanCopyUtil
 * @information on version 1.0 be created by @xwltz at 2021/12/28 9:57
 */

public class BeanUtils extends cn.hutool.core.bean.BeanUtil {

	private static ApplicationContext context;

	public static void setContext(ApplicationContext context) {
		BeanUtils.context = context;
	}

	public static ApplicationContext getContext() {
		return context;
	}

	public static Object getBean(@Nonnull String beanName) {
		return context.getBean(beanName);
	}

	public static <T> T getBean(@Nonnull Class<T> beanClass) {
		return context.getBean(beanClass);
	}

	public static String getProperty(@Nonnull String name) {
		return context.getEnvironment().getProperty(name);
	}

	/**
	 * Bean属性复制工具方法。
	 *
	 * @param dest 目标对象
	 * @param src 源对象
	 */
	public static void copyBeanProp(Object dest, Object src)
	{
		try
		{
			copyProperties(src, dest);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * 单对象基于class创建拷贝
	 *
	 * @param source      数据来源实体
	 * @param copyOptions copy条件
	 * @param desc        描述对象 转换后的对象
	 * @return desc
	 */
	public static <T, V> V oneCopy(T source, CopyOptions copyOptions, Class<V> desc) {
		V v = ReflectUtil.newInstanceIfPossible(desc);
		return oneCopy(source, copyOptions, v);
	}

	/**
	 * 单对象基于对象创建拷贝
	 *
	 * @param source      数据来源实体
	 * @param copyOptions copy条件
	 * @param desc        转换后的对象
	 * @return desc
	 */
	public static <T, V> V oneCopy(T source, CopyOptions copyOptions, V desc) {
		if (ObjectUtil.isNull(source)) {
			return null;
		}
		return BeanCopier.create(source, desc, copyOptions).copy();
	}

	/**
	 * 列表对象基于class创建拷贝
	 *
	 * @param sourceList  数据来源实体列表
	 * @param copyOptions copy条件
	 * @param desc        描述对象 转换后的对象
	 * @return desc
	 */
	public static <T, V> List<V> listCopy(List<T> sourceList, CopyOptions copyOptions, Class<V> desc) {
		if (ObjectUtil.isNull(sourceList)) {
			return null;
		}
		if (CollUtil.isEmpty(sourceList)) {
			return CollUtil.newArrayList();
		}
		return sourceList.stream().map(source -> oneCopy(source, copyOptions, desc)).collect(Collectors.toList());
	}
}
